home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / python2.4 / httplib.pyo (.txt) < prev    next >
Python Compiled Bytecode  |  2005-10-18  |  36KB  |  1,306 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.4)
  3.  
  4. '''HTTP/1.1 client library
  5.  
  6. <intro stuff goes here>
  7. <other stuff, too>
  8.  
  9. HTTPConnection go through a number of "states", which defines when a client
  10. may legally make another request or fetch the response for a particular
  11. request. This diagram details these state transitions:
  12.  
  13.     (null)
  14.       |
  15.       | HTTPConnection()
  16.       v
  17.     Idle
  18.       |
  19.       | putrequest()
  20.       v
  21.     Request-started
  22.       |
  23.       | ( putheader() )*  endheaders()
  24.       v
  25.     Request-sent
  26.       |
  27.       | response = getresponse()
  28.       v
  29.     Unread-response   [Response-headers-read]
  30.       |\\____________________
  31.       |                     |
  32.       | response.read()     | putrequest()
  33.       v                     v
  34.     Idle                  Req-started-unread-response
  35.                      ______/|
  36.                    /        |
  37.    response.read() |        | ( putheader() )*  endheaders()
  38.                    v        v
  39.        Request-started    Req-sent-unread-response
  40.                             |
  41.                             | response.read()
  42.                             v
  43.                           Request-sent
  44.  
  45. This diagram presents the following rules:
  46.   -- a second request may not be started until {response-headers-read}
  47.   -- a response [object] cannot be retrieved until {request-sent}
  48.   -- there is no differentiation between an unread response body and a
  49.      partially read response body
  50.  
  51. Note: this enforcement is applied by the HTTPConnection class. The
  52.       HTTPResponse class does not enforce this state machine, which
  53.       implies sophisticated clients may accelerate the request/response
  54.       pipeline. Caution should be taken, though: accelerating the states
  55.       beyond the above pattern may imply knowledge of the server\'s
  56.       connection-close behavior for certain requests. For example, it
  57.       is impossible to tell whether the server will close the connection
  58.       UNTIL the response headers have been read; this means that further
  59.       requests cannot be placed into the pipeline until it is known that
  60.       the server will NOT be closing the connection.
  61.  
  62. Logical State                  __state            __response
  63. -------------                  -------            ----------
  64. Idle                           _CS_IDLE           None
  65. Request-started                _CS_REQ_STARTED    None
  66. Request-sent                   _CS_REQ_SENT       None
  67. Unread-response                _CS_IDLE           <response_class>
  68. Req-started-unread-response    _CS_REQ_STARTED    <response_class>
  69. Req-sent-unread-response       _CS_REQ_SENT       <response_class>
  70. '''
  71. import errno
  72. import mimetools
  73. import socket
  74. from urlparse import urlsplit
  75.  
  76. try:
  77.     from cStringIO import StringIO
  78. except ImportError:
  79.     from StringIO import StringIO
  80.  
  81. __all__ = [
  82.     'HTTP',
  83.     'HTTPResponse',
  84.     'HTTPConnection',
  85.     'HTTPSConnection',
  86.     'HTTPException',
  87.     'NotConnected',
  88.     'UnknownProtocol',
  89.     'UnknownTransferEncoding',
  90.     'UnimplementedFileMode',
  91.     'IncompleteRead',
  92.     'InvalidURL',
  93.     'ImproperConnectionState',
  94.     'CannotSendRequest',
  95.     'CannotSendHeader',
  96.     'ResponseNotReady',
  97.     'BadStatusLine',
  98.     'error']
  99. HTTP_PORT = 80
  100. HTTPS_PORT = 443
  101. _UNKNOWN = 'UNKNOWN'
  102. _CS_IDLE = 'Idle'
  103. _CS_REQ_STARTED = 'Request-started'
  104. _CS_REQ_SENT = 'Request-sent'
  105. CONTINUE = 100
  106. SWITCHING_PROTOCOLS = 101
  107. PROCESSING = 102
  108. OK = 200
  109. CREATED = 201
  110. ACCEPTED = 202
  111. NON_AUTHORITATIVE_INFORMATION = 203
  112. NO_CONTENT = 204
  113. RESET_CONTENT = 205
  114. PARTIAL_CONTENT = 206
  115. MULTI_STATUS = 207
  116. IM_USED = 226
  117. MULTIPLE_CHOICES = 300
  118. MOVED_PERMANENTLY = 301
  119. FOUND = 302
  120. SEE_OTHER = 303
  121. NOT_MODIFIED = 304
  122. USE_PROXY = 305
  123. TEMPORARY_REDIRECT = 307
  124. BAD_REQUEST = 400
  125. UNAUTHORIZED = 401
  126. PAYMENT_REQUIRED = 402
  127. FORBIDDEN = 403
  128. NOT_FOUND = 404
  129. METHOD_NOT_ALLOWED = 405
  130. NOT_ACCEPTABLE = 406
  131. PROXY_AUTHENTICATION_REQUIRED = 407
  132. REQUEST_TIMEOUT = 408
  133. CONFLICT = 409
  134. GONE = 410
  135. LENGTH_REQUIRED = 411
  136. PRECONDITION_FAILED = 412
  137. REQUEST_ENTITY_TOO_LARGE = 413
  138. REQUEST_URI_TOO_LONG = 414
  139. UNSUPPORTED_MEDIA_TYPE = 415
  140. REQUESTED_RANGE_NOT_SATISFIABLE = 416
  141. EXPECTATION_FAILED = 417
  142. UNPROCESSABLE_ENTITY = 422
  143. LOCKED = 423
  144. FAILED_DEPENDENCY = 424
  145. UPGRADE_REQUIRED = 426
  146. INTERNAL_SERVER_ERROR = 500
  147. NOT_IMPLEMENTED = 501
  148. BAD_GATEWAY = 502
  149. SERVICE_UNAVAILABLE = 503
  150. GATEWAY_TIMEOUT = 504
  151. HTTP_VERSION_NOT_SUPPORTED = 505
  152. INSUFFICIENT_STORAGE = 507
  153. NOT_EXTENDED = 510
  154.  
  155. class HTTPMessage(mimetools.Message):
  156.     
  157.     def addheader(self, key, value):
  158.         '''Add header for field key handling repeats.'''
  159.         prev = self.dict.get(key)
  160.         if prev is None:
  161.             self.dict[key] = value
  162.         else:
  163.             combined = ', '.join((prev, value))
  164.             self.dict[key] = combined
  165.  
  166.     
  167.     def addcontinue(self, key, more):
  168.         '''Add more field data from a continuation line.'''
  169.         prev = self.dict[key]
  170.         self.dict[key] = prev + '\n ' + more
  171.  
  172.     
  173.     def readheaders(self):
  174.         '''Read header lines.
  175.  
  176.         Read header lines up to the entirely blank line that terminates them.
  177.         The (normally blank) line that ends the headers is skipped, but not
  178.         included in the returned list.  If a non-header line ends the headers,
  179.         (which is an error), an attempt is made to backspace over it; it is
  180.         never included in the returned list.
  181.  
  182.         The variable self.status is set to the empty string if all went well,
  183.         otherwise it is an error message.  The variable self.headers is a
  184.         completely uninterpreted list of lines contained in the header (so
  185.         printing them will reproduce the header exactly as it appears in the
  186.         file).
  187.  
  188.         If multiple header fields with the same name occur, they are combined
  189.         according to the rules in RFC 2616 sec 4.2:
  190.  
  191.         Appending each subsequent field-value to the first, each separated
  192.         by a comma. The order in which header fields with the same field-name
  193.         are received is significant to the interpretation of the combined
  194.         field value.
  195.         '''
  196.         self.dict = { }
  197.         self.unixfrom = ''
  198.         self.headers = hlist = []
  199.         self.status = ''
  200.         headerseen = ''
  201.         firstline = 1
  202.         startofline = None
  203.         unread = None
  204.         tell = None
  205.         if hasattr(self.fp, 'unread'):
  206.             unread = self.fp.unread
  207.         elif self.seekable:
  208.             tell = self.fp.tell
  209.         
  210.         while True:
  211.             if tell:
  212.                 
  213.                 try:
  214.                     startofline = tell()
  215.                 except IOError:
  216.                     startofline = None
  217.                     tell = None
  218.                     self.seekable = 0
  219.                 except:
  220.                     None<EXCEPTION MATCH>IOError
  221.                 
  222.  
  223.             None<EXCEPTION MATCH>IOError
  224.             line = self.fp.readline()
  225.             if not line:
  226.                 self.status = 'EOF in headers'
  227.                 break
  228.             
  229.             if firstline and line.startswith('From '):
  230.                 self.unixfrom = self.unixfrom + line
  231.                 continue
  232.             
  233.             firstline = 0
  234.             if headerseen and line[0] in ' \t':
  235.                 hlist.append(line)
  236.                 self.addcontinue(headerseen, line.strip())
  237.                 continue
  238.             elif self.iscomment(line):
  239.                 continue
  240.             elif self.islast(line):
  241.                 break
  242.             
  243.             headerseen = self.isheader(line)
  244.             if headerseen:
  245.                 hlist.append(line)
  246.                 self.addheader(headerseen, line[len(headerseen) + 1:].strip())
  247.                 continue
  248.                 continue
  249.             if not self.dict:
  250.                 self.status = 'No headers'
  251.             else:
  252.                 self.status = 'Non-header line where header expected'
  253.             if unread:
  254.                 unread(line)
  255.             elif tell:
  256.                 self.fp.seek(startofline)
  257.             else:
  258.                 self.status = self.status + '; bad seek'
  259.             break
  260.  
  261.  
  262.  
  263. class HTTPResponse:
  264.     
  265.     def __init__(self, sock, debuglevel = 0, strict = 0, method = None):
  266.         self.fp = sock.makefile('rb', 0)
  267.         self.debuglevel = debuglevel
  268.         self.strict = strict
  269.         self._method = method
  270.         self.msg = None
  271.         self.version = _UNKNOWN
  272.         self.status = _UNKNOWN
  273.         self.reason = _UNKNOWN
  274.         self.chunked = _UNKNOWN
  275.         self.chunk_left = _UNKNOWN
  276.         self.length = _UNKNOWN
  277.         self.will_close = _UNKNOWN
  278.  
  279.     
  280.     def _read_status(self):
  281.         line = self.fp.readline()
  282.         if self.debuglevel > 0:
  283.             print 'reply:', repr(line)
  284.         
  285.         if not line:
  286.             raise BadStatusLine(line)
  287.         
  288.         
  289.         try:
  290.             (version, status, reason) = line.split(None, 2)
  291.         except ValueError:
  292.             
  293.             try:
  294.                 (version, status) = line.split(None, 1)
  295.                 reason = ''
  296.             except ValueError:
  297.                 version = ''
  298.             except:
  299.                 None<EXCEPTION MATCH>ValueError
  300.             
  301.  
  302.             None<EXCEPTION MATCH>ValueError
  303.  
  304.         if not version.startswith('HTTP/'):
  305.             if self.strict:
  306.                 self.close()
  307.                 raise BadStatusLine(line)
  308.             else:
  309.                 self.fp = LineAndFileWrapper(line, self.fp)
  310.                 return ('HTTP/0.9', 200, '')
  311.         
  312.         
  313.         try:
  314.             status = int(status)
  315.             if status < 100 or status > 999:
  316.                 raise BadStatusLine(line)
  317.         except ValueError:
  318.             raise BadStatusLine(line)
  319.  
  320.         return (version, status, reason)
  321.  
  322.     
  323.     def begin(self):
  324.         if self.msg is not None:
  325.             return None
  326.         
  327.         while True:
  328.             (version, status, reason) = self._read_status()
  329.             if status != CONTINUE:
  330.                 break
  331.             
  332.             while True:
  333.                 skip = self.fp.readline().strip()
  334.                 if not skip:
  335.                     break
  336.                 
  337.                 if self.debuglevel > 0:
  338.                     print 'header:', skip
  339.                     continue
  340.         self.status = status
  341.         self.reason = reason.strip()
  342.         if version == 'HTTP/1.0':
  343.             self.version = 10
  344.         elif version.startswith('HTTP/1.'):
  345.             self.version = 11
  346.         elif version == 'HTTP/0.9':
  347.             self.version = 9
  348.         else:
  349.             raise UnknownProtocol(version)
  350.         if self.version == 9:
  351.             self.length = None
  352.             self.chunked = 0
  353.             self.will_close = 1
  354.             self.msg = HTTPMessage(StringIO())
  355.             return None
  356.         
  357.         self.msg = HTTPMessage(self.fp, 0)
  358.         if self.debuglevel > 0:
  359.             for hdr in self.msg.headers:
  360.                 print 'header:', hdr,
  361.             
  362.         
  363.         self.msg.fp = None
  364.         tr_enc = self.msg.getheader('transfer-encoding')
  365.         if tr_enc and tr_enc.lower() == 'chunked':
  366.             self.chunked = 1
  367.             self.chunk_left = None
  368.         else:
  369.             self.chunked = 0
  370.         self.will_close = self._check_close()
  371.         length = self.msg.getheader('content-length')
  372.         if length and not (self.chunked):
  373.             
  374.             try:
  375.                 self.length = int(length)
  376.             except ValueError:
  377.                 self.length = None
  378.             except:
  379.                 None<EXCEPTION MATCH>ValueError
  380.             
  381.  
  382.         None<EXCEPTION MATCH>ValueError
  383.         self.length = None
  384.         if not status == NO_CONTENT and status == NOT_MODIFIED:
  385.             if status <= status:
  386.                 pass
  387.             elif status < 200 or self._method == 'HEAD':
  388.                 self.length = 0
  389.             
  390.         if not (self.will_close) and not (self.chunked) and self.length is None:
  391.             self.will_close = 1
  392.         
  393.  
  394.     
  395.     def _check_close(self):
  396.         conn = self.msg.getheader('connection')
  397.         if self.version == 11:
  398.             conn = self.msg.getheader('connection')
  399.             if conn and 'close' in conn.lower():
  400.                 return True
  401.             
  402.             return False
  403.         
  404.         if self.msg.getheader('keep-alive'):
  405.             return False
  406.         
  407.         if conn and 'keep-alive' in conn.lower():
  408.             return False
  409.         
  410.         pconn = self.msg.getheader('proxy-connection')
  411.         if pconn and 'keep-alive' in pconn.lower():
  412.             return False
  413.         
  414.         return True
  415.  
  416.     
  417.     def close(self):
  418.         if self.fp:
  419.             self.fp.close()
  420.             self.fp = None
  421.         
  422.  
  423.     
  424.     def isclosed(self):
  425.         return self.fp is None
  426.  
  427.     
  428.     def read(self, amt = None):
  429.         if self.fp is None:
  430.             return ''
  431.         
  432.         if self.chunked:
  433.             return self._read_chunked(amt)
  434.         
  435.         if amt is None:
  436.             if self.length is None:
  437.                 s = self.fp.read()
  438.             else:
  439.                 s = self._safe_read(self.length)
  440.                 self.length = 0
  441.             self.close()
  442.             return s
  443.         
  444.         if self.length is not None:
  445.             if amt > self.length:
  446.                 amt = self.length
  447.             
  448.         
  449.         s = self.fp.read(amt)
  450.         if self.length is not None:
  451.             self.length -= len(s)
  452.         
  453.         return s
  454.  
  455.     
  456.     def _read_chunked(self, amt):
  457.         chunk_left = self.chunk_left
  458.         value = ''
  459.         while True:
  460.             if chunk_left is None:
  461.                 line = self.fp.readline()
  462.                 i = line.find(';')
  463.                 if i >= 0:
  464.                     line = line[:i]
  465.                 
  466.                 chunk_left = int(line, 16)
  467.                 if chunk_left == 0:
  468.                     break
  469.                 
  470.             
  471.             if amt is None:
  472.                 value += self._safe_read(chunk_left)
  473.             elif amt < chunk_left:
  474.                 value += self._safe_read(amt)
  475.                 self.chunk_left = chunk_left - amt
  476.                 return value
  477.             elif amt == chunk_left:
  478.                 value += self._safe_read(amt)
  479.                 self._safe_read(2)
  480.                 self.chunk_left = None
  481.                 return value
  482.             else:
  483.                 value += self._safe_read(chunk_left)
  484.                 amt -= chunk_left
  485.             self._safe_read(2)
  486.             chunk_left = None
  487.         while True:
  488.             line = self.fp.readline()
  489.             if line == '\r\n':
  490.                 break
  491.                 continue
  492.         self.close()
  493.         return value
  494.  
  495.     
  496.     def _safe_read(self, amt):
  497.         '''Read the number of bytes requested, compensating for partial reads.
  498.  
  499.         Normally, we have a blocking socket, but a read() can be interrupted
  500.         by a signal (resulting in a partial read).
  501.  
  502.         Note that we cannot distinguish between EOF and an interrupt when zero
  503.         bytes have been read. IncompleteRead() will be raised in this
  504.         situation.
  505.  
  506.         This function should be used when <amt> bytes "should" be present for
  507.         reading. If the bytes are truly not available (due to EOF), then the
  508.         IncompleteRead exception can be used to detect the problem.
  509.         '''
  510.         s = ''
  511.         while amt > 0:
  512.             chunk = self.fp.read(amt)
  513.             if not chunk:
  514.                 raise IncompleteRead(s)
  515.             
  516.             s += chunk
  517.             amt -= len(chunk)
  518.         return s
  519.  
  520.     
  521.     def getheader(self, name, default = None):
  522.         if self.msg is None:
  523.             raise ResponseNotReady()
  524.         
  525.         return self.msg.getheader(name, default)
  526.  
  527.     
  528.     def getheaders(self):
  529.         '''Return list of (header, value) tuples.'''
  530.         if self.msg is None:
  531.             raise ResponseNotReady()
  532.         
  533.         return self.msg.items()
  534.  
  535.  
  536.  
  537. class HTTPConnection:
  538.     _http_vsn = 11
  539.     _http_vsn_str = 'HTTP/1.1'
  540.     response_class = HTTPResponse
  541.     default_port = HTTP_PORT
  542.     auto_open = 1
  543.     debuglevel = 0
  544.     strict = 0
  545.     
  546.     def __init__(self, host, port = None, strict = None):
  547.         self.sock = None
  548.         self._buffer = []
  549.         self._HTTPConnection__response = None
  550.         self._HTTPConnection__state = _CS_IDLE
  551.         self._method = None
  552.         self._set_hostport(host, port)
  553.         if strict is not None:
  554.             self.strict = strict
  555.         
  556.  
  557.     
  558.     def _set_hostport(self, host, port):
  559.         if port is None:
  560.             i = host.rfind(':')
  561.             j = host.rfind(']')
  562.             if i > j:
  563.                 
  564.                 try:
  565.                     port = int(host[i + 1:])
  566.                 except ValueError:
  567.                     raise InvalidURL("nonnumeric port: '%s'" % host[i + 1:])
  568.  
  569.                 host = host[:i]
  570.             else:
  571.                 port = self.default_port
  572.             if host and host[0] == '[' and host[-1] == ']':
  573.                 host = host[1:-1]
  574.             
  575.         
  576.         self.host = host
  577.         self.port = port
  578.  
  579.     
  580.     def set_debuglevel(self, level):
  581.         self.debuglevel = level
  582.  
  583.     
  584.     def connect(self):
  585.         '''Connect to the host and port specified in __init__.'''
  586.         msg = 'getaddrinfo returns an empty list'
  587.         for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM):
  588.             (af, socktype, proto, canonname, sa) = res
  589.             
  590.             try:
  591.                 self.sock = socket.socket(af, socktype, proto)
  592.                 if self.debuglevel > 0:
  593.                     print 'connect: (%s, %s)' % (self.host, self.port)
  594.                 
  595.                 self.sock.connect(sa)
  596.             except socket.error:
  597.                 msg = None
  598.                 if self.debuglevel > 0:
  599.                     print 'connect fail:', (self.host, self.port)
  600.                 
  601.                 if self.sock:
  602.                     self.sock.close()
  603.                 
  604.                 self.sock = None
  605.                 continue
  606.  
  607.             break
  608.         
  609.         if not self.sock:
  610.             raise socket.error, msg
  611.         
  612.  
  613.     
  614.     def close(self):
  615.         '''Close the connection to the HTTP server.'''
  616.         if self.sock:
  617.             self.sock.close()
  618.             self.sock = None
  619.         
  620.         if self._HTTPConnection__response:
  621.             self._HTTPConnection__response.close()
  622.             self._HTTPConnection__response = None
  623.         
  624.         self._HTTPConnection__state = _CS_IDLE
  625.  
  626.     
  627.     def send(self, str):
  628.         """Send `str' to the server."""
  629.         if self.sock is None:
  630.             if self.auto_open:
  631.                 self.connect()
  632.             else:
  633.                 raise NotConnected()
  634.         
  635.         if self.debuglevel > 0:
  636.             print 'send:', repr(str)
  637.         
  638.         
  639.         try:
  640.             self.sock.sendall(str)
  641.         except socket.error:
  642.             v = None
  643.             if v[0] == 32:
  644.                 self.close()
  645.             
  646.             raise 
  647.  
  648.  
  649.     
  650.     def _output(self, s):
  651.         '''Add a line of output to the current request buffer.
  652.  
  653.         Assumes that the line does *not* end with \\r\\n.
  654.         '''
  655.         self._buffer.append(s)
  656.  
  657.     
  658.     def _send_output(self):
  659.         '''Send the currently buffered request and clear the buffer.
  660.  
  661.         Appends an extra \\r\\n to the buffer.
  662.         '''
  663.         self._buffer.extend(('', ''))
  664.         msg = '\r\n'.join(self._buffer)
  665.         del self._buffer[:]
  666.         self.send(msg)
  667.  
  668.     
  669.     def putrequest(self, method, url, skip_host = 0, skip_accept_encoding = 0):
  670.         """Send a request to the server.
  671.  
  672.         `method' specifies an HTTP request method, e.g. 'GET'.
  673.         `url' specifies the object being requested, e.g. '/index.html'.
  674.         `skip_host' if True does not add automatically a 'Host:' header
  675.         `skip_accept_encoding' if True does not add automatically an
  676.            'Accept-Encoding:' header
  677.         """
  678.         if self._HTTPConnection__response and self._HTTPConnection__response.isclosed():
  679.             self._HTTPConnection__response = None
  680.         
  681.         if self._HTTPConnection__state == _CS_IDLE:
  682.             self._HTTPConnection__state = _CS_REQ_STARTED
  683.         else:
  684.             raise CannotSendRequest()
  685.         self._method = method
  686.         if not url:
  687.             url = '/'
  688.         
  689.         str = '%s %s %s' % (method, url, self._http_vsn_str)
  690.         self._output(str)
  691.         if self._http_vsn == 11:
  692.             if not skip_host:
  693.                 netloc = ''
  694.                 if url.startswith('http'):
  695.                     (nil, netloc, nil, nil, nil) = urlsplit(url)
  696.                 
  697.                 if netloc:
  698.                     self.putheader('Host', netloc.encode('idna'))
  699.                 elif self.port == HTTP_PORT:
  700.                     self.putheader('Host', self.host.encode('idna'))
  701.                 else:
  702.                     self.putheader('Host', '%s:%s' % (self.host.encode('idna'), self.port))
  703.             
  704.             if not skip_accept_encoding:
  705.                 self.putheader('Accept-Encoding', 'identity')
  706.             
  707.         
  708.  
  709.     
  710.     def putheader(self, header, value):
  711.         """Send a request header line to the server.
  712.  
  713.         For example: h.putheader('Accept', 'text/html')
  714.         """
  715.         if self._HTTPConnection__state != _CS_REQ_STARTED:
  716.             raise CannotSendHeader()
  717.         
  718.         str = '%s: %s' % (header, value)
  719.         self._output(str)
  720.  
  721.     
  722.     def endheaders(self):
  723.         '''Indicate that the last header line has been sent to the server.'''
  724.         if self._HTTPConnection__state == _CS_REQ_STARTED:
  725.             self._HTTPConnection__state = _CS_REQ_SENT
  726.         else:
  727.             raise CannotSendHeader()
  728.         self._send_output()
  729.  
  730.     
  731.     def request(self, method, url, body = None, headers = { }):
  732.         '''Send a complete request to the server.'''
  733.         
  734.         try:
  735.             self._send_request(method, url, body, headers)
  736.         except socket.error:
  737.             v = None
  738.             if v[0] != 32 or not (self.auto_open):
  739.                 raise 
  740.             
  741.             self._send_request(method, url, body, headers)
  742.  
  743.  
  744.     
  745.     def _send_request(self, method, url, body, headers):
  746.         header_names = []([ k.lower() for k in headers ])
  747.         skips = { }
  748.         if 'accept-encoding' in header_names:
  749.             skips['skip_accept_encoding'] = 1
  750.         
  751.         self.putrequest(method, url, **skips)
  752.         if body and 'content-length' not in header_names:
  753.             self.putheader('Content-Length', str(len(body)))
  754.         
  755.         for hdr, value in headers.iteritems():
  756.             self.putheader(hdr, value)
  757.         
  758.         self.endheaders()
  759.         if body:
  760.             self.send(body)
  761.         
  762.  
  763.     
  764.     def getresponse(self):
  765.         '''Get the response from the server.'''
  766.         if self._HTTPConnection__response and self._HTTPConnection__response.isclosed():
  767.             self._HTTPConnection__response = None
  768.         
  769.         if self._HTTPConnection__state != _CS_REQ_SENT or self._HTTPConnection__response:
  770.             raise ResponseNotReady()
  771.         
  772.         if self.debuglevel > 0:
  773.             response = self.response_class(self.sock, self.debuglevel, strict = self.strict, method = self._method)
  774.         else:
  775.             response = self.response_class(self.sock, strict = self.strict, method = self._method)
  776.         response.begin()
  777.         self._HTTPConnection__state = _CS_IDLE
  778.         if response.will_close:
  779.             self.close()
  780.         else:
  781.             self._HTTPConnection__response = response
  782.         return response
  783.  
  784.  
  785.  
  786. class SharedSocket:
  787.     
  788.     def __init__(self, sock):
  789.         self.sock = sock
  790.         self._refcnt = 0
  791.  
  792.     
  793.     def incref(self):
  794.         self._refcnt += 1
  795.  
  796.     
  797.     def decref(self):
  798.         self._refcnt -= 1
  799.         if self._refcnt == 0:
  800.             self.sock.close()
  801.         
  802.  
  803.     
  804.     def __del__(self):
  805.         self.sock.close()
  806.  
  807.  
  808.  
  809. class SharedSocketClient:
  810.     
  811.     def __init__(self, shared):
  812.         self._closed = 0
  813.         self._shared = shared
  814.         self._shared.incref()
  815.         self._sock = shared.sock
  816.  
  817.     
  818.     def close(self):
  819.         if not self._closed:
  820.             self._shared.decref()
  821.             self._closed = 1
  822.             self._shared = None
  823.         
  824.  
  825.  
  826.  
  827. class SSLFile(SharedSocketClient):
  828.     '''File-like object wrapping an SSL socket.'''
  829.     BUFSIZE = 8192
  830.     
  831.     def __init__(self, sock, ssl, bufsize = None):
  832.         SharedSocketClient.__init__(self, sock)
  833.         self._ssl = ssl
  834.         self._buf = ''
  835.         if not bufsize:
  836.             pass
  837.         self._bufsize = self.__class__.BUFSIZE
  838.  
  839.     
  840.     def _read(self):
  841.         buf = ''
  842.         while True:
  843.             
  844.             try:
  845.                 buf = self._ssl.read(self._bufsize)
  846.             except socket.sslerror:
  847.                 err = None
  848.                 if err[0] == socket.SSL_ERROR_WANT_READ or err[0] == socket.SSL_ERROR_WANT_WRITE:
  849.                     continue
  850.                 
  851.                 if err[0] == socket.SSL_ERROR_ZERO_RETURN or err[0] == socket.SSL_ERROR_EOF:
  852.                     break
  853.                 
  854.                 raise 
  855.                 continue
  856.                 except socket.error:
  857.                     err = None
  858.                     if err[0] == errno.EINTR:
  859.                         continue
  860.                     
  861.                     if err[0] == errno.EBADF:
  862.                         break
  863.                     
  864.                     raise 
  865.                     continue
  866.                 else:
  867.                     break
  868.                 None<EXCEPTION MATCH>socket.error
  869.             return buf
  870.  
  871.  
  872.     
  873.     def read(self, size = None):
  874.         L = [
  875.             self._buf]
  876.         avail = len(self._buf)
  877.         while size is None or avail < size:
  878.             s = self._read()
  879.             if s == '':
  880.                 break
  881.             
  882.             L.append(s)
  883.             avail += len(s)
  884.         all = ''.join(L)
  885.         if size is None:
  886.             self._buf = ''
  887.             return all
  888.         else:
  889.             self._buf = all[size:]
  890.             return all[:size]
  891.  
  892.     
  893.     def readline(self):
  894.         L = [
  895.             self._buf]
  896.         self._buf = ''
  897.         while None:
  898.             i = L[-1].find('\n')
  899.             if i >= 0:
  900.                 break
  901.             
  902.             s = self._read()
  903.             if s == '':
  904.                 break
  905.             
  906.         if i == -1:
  907.             return ''.join(L)
  908.         else:
  909.             all = ''.join(L)
  910.             i = all.find('\n') + 1
  911.             line = all[:i]
  912.             self._buf = all[i:]
  913.             return line
  914.  
  915.     
  916.     def readlines(self, sizehint = 0):
  917.         total = 0
  918.         list = []
  919.         while True:
  920.             line = self.readline()
  921.             if not line:
  922.                 break
  923.             
  924.             list.append(line)
  925.             total += len(line)
  926.             if sizehint and total >= sizehint:
  927.                 break
  928.                 continue
  929.         return list
  930.  
  931.     
  932.     def fileno(self):
  933.         return self._sock.fileno()
  934.  
  935.     
  936.     def __iter__(self):
  937.         return self
  938.  
  939.     
  940.     def next(self):
  941.         line = self.readline()
  942.         if not line:
  943.             raise StopIteration
  944.         
  945.         return line
  946.  
  947.  
  948.  
  949. class FakeSocket(SharedSocketClient):
  950.     
  951.     class _closedsocket:
  952.         
  953.         def __getattr__(self, name):
  954.             raise error(9, 'Bad file descriptor')
  955.  
  956.  
  957.     
  958.     def __init__(self, sock, ssl):
  959.         sock = SharedSocket(sock)
  960.         SharedSocketClient.__init__(self, sock)
  961.         self._ssl = ssl
  962.  
  963.     
  964.     def close(self):
  965.         SharedSocketClient.close(self)
  966.         self._sock = self.__class__._closedsocket()
  967.  
  968.     
  969.     def makefile(self, mode, bufsize = None):
  970.         if mode != 'r' and mode != 'rb':
  971.             raise UnimplementedFileMode()
  972.         
  973.         return SSLFile(self._shared, self._ssl, bufsize)
  974.  
  975.     
  976.     def send(self, stuff, flags = 0):
  977.         return self._ssl.write(stuff)
  978.  
  979.     sendall = send
  980.     
  981.     def recv(self, len = 1024, flags = 0):
  982.         return self._ssl.read(len)
  983.  
  984.     
  985.     def __getattr__(self, attr):
  986.         return getattr(self._sock, attr)
  987.  
  988.  
  989.  
  990. class HTTPSConnection(HTTPConnection):
  991.     '''This class allows communication via SSL.'''
  992.     default_port = HTTPS_PORT
  993.     
  994.     def __init__(self, host, port = None, key_file = None, cert_file = None, strict = None):
  995.         HTTPConnection.__init__(self, host, port, strict)
  996.         self.key_file = key_file
  997.         self.cert_file = cert_file
  998.  
  999.     
  1000.     def connect(self):
  1001.         '''Connect to a host on a given (SSL) port.'''
  1002.         sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  1003.         sock.connect((self.host, self.port))
  1004.         ssl = socket.ssl(sock, self.key_file, self.cert_file)
  1005.         self.sock = FakeSocket(sock, ssl)
  1006.  
  1007.  
  1008.  
  1009. class HTTP:
  1010.     '''Compatibility class with httplib.py from 1.5.'''
  1011.     _http_vsn = 10
  1012.     _http_vsn_str = 'HTTP/1.0'
  1013.     debuglevel = 0
  1014.     _connection_class = HTTPConnection
  1015.     
  1016.     def __init__(self, host = '', port = None, strict = None):
  1017.         '''Provide a default host, since the superclass requires one.'''
  1018.         if port == 0:
  1019.             port = None
  1020.         
  1021.         self._setup(self._connection_class(host, port, strict))
  1022.  
  1023.     
  1024.     def _setup(self, conn):
  1025.         self._conn = conn
  1026.         self.send = conn.send
  1027.         self.putrequest = conn.putrequest
  1028.         self.endheaders = conn.endheaders
  1029.         self.set_debuglevel = conn.set_debuglevel
  1030.         conn._http_vsn = self._http_vsn
  1031.         conn._http_vsn_str = self._http_vsn_str
  1032.         self.file = None
  1033.  
  1034.     
  1035.     def connect(self, host = None, port = None):
  1036.         """Accept arguments to set the host/port, since the superclass doesn't."""
  1037.         if host is not None:
  1038.             self._conn._set_hostport(host, port)
  1039.         
  1040.         self._conn.connect()
  1041.  
  1042.     
  1043.     def getfile(self):
  1044.         """Provide a getfile, since the superclass' does not use this concept."""
  1045.         return self.file
  1046.  
  1047.     
  1048.     def putheader(self, header, *values):
  1049.         '''The superclass allows only one value argument.'''
  1050.         self._conn.putheader(header, '\r\n\t'.join(values))
  1051.  
  1052.     
  1053.     def getreply(self):
  1054.         '''Compat definition since superclass does not define it.
  1055.  
  1056.         Returns a tuple consisting of:
  1057.         - server status code (e.g. \'200\' if all goes well)
  1058.         - server "reason" corresponding to status code
  1059.         - any RFC822 headers in the response from the server
  1060.         '''
  1061.         
  1062.         try:
  1063.             response = self._conn.getresponse()
  1064.         except BadStatusLine:
  1065.             e = None
  1066.             self.file = self._conn.sock.makefile('rb', 0)
  1067.             self.close()
  1068.             self.headers = None
  1069.             return (-1, e.line, None)
  1070.  
  1071.         self.headers = response.msg
  1072.         self.file = response.fp
  1073.         return (response.status, response.reason, response.msg)
  1074.  
  1075.     
  1076.     def close(self):
  1077.         self._conn.close()
  1078.         self.file = None
  1079.  
  1080.  
  1081. if hasattr(socket, 'ssl'):
  1082.     
  1083.     class HTTPS(HTTP):
  1084.         '''Compatibility with 1.5 httplib interface
  1085.  
  1086.         Python 1.5.2 did not have an HTTPS class, but it defined an
  1087.         interface for sending http requests that is also useful for
  1088.         https.
  1089.         '''
  1090.         _connection_class = HTTPSConnection
  1091.         
  1092.         def __init__(self, host = '', port = None, key_file = None, cert_file = None, strict = None):
  1093.             if port == 0:
  1094.                 port = None
  1095.             
  1096.             self._setup(self._connection_class(host, port, key_file, cert_file, strict))
  1097.             self.key_file = key_file
  1098.             self.cert_file = cert_file
  1099.  
  1100.  
  1101.  
  1102.  
  1103. class HTTPException(Exception):
  1104.     pass
  1105.  
  1106.  
  1107. class NotConnected(HTTPException):
  1108.     pass
  1109.  
  1110.  
  1111. class InvalidURL(HTTPException):
  1112.     pass
  1113.  
  1114.  
  1115. class UnknownProtocol(HTTPException):
  1116.     
  1117.     def __init__(self, version):
  1118.         self.args = (version,)
  1119.         self.version = version
  1120.  
  1121.  
  1122.  
  1123. class UnknownTransferEncoding(HTTPException):
  1124.     pass
  1125.  
  1126.  
  1127. class UnimplementedFileMode(HTTPException):
  1128.     pass
  1129.  
  1130.  
  1131. class IncompleteRead(HTTPException):
  1132.     
  1133.     def __init__(self, partial):
  1134.         self.args = (partial,)
  1135.         self.partial = partial
  1136.  
  1137.  
  1138.  
  1139. class ImproperConnectionState(HTTPException):
  1140.     pass
  1141.  
  1142.  
  1143. class CannotSendRequest(ImproperConnectionState):
  1144.     pass
  1145.  
  1146.  
  1147. class CannotSendHeader(ImproperConnectionState):
  1148.     pass
  1149.  
  1150.  
  1151. class ResponseNotReady(ImproperConnectionState):
  1152.     pass
  1153.  
  1154.  
  1155. class BadStatusLine(HTTPException):
  1156.     
  1157.     def __init__(self, line):
  1158.         self.args = (line,)
  1159.         self.line = line
  1160.  
  1161.  
  1162. error = HTTPException
  1163.  
  1164. class LineAndFileWrapper:
  1165.     '''A limited file-like object for HTTP/0.9 responses.'''
  1166.     
  1167.     def __init__(self, line, file):
  1168.         self._line = line
  1169.         self._file = file
  1170.         self._line_consumed = 0
  1171.         self._line_offset = 0
  1172.         self._line_left = len(line)
  1173.  
  1174.     
  1175.     def __getattr__(self, attr):
  1176.         return getattr(self._file, attr)
  1177.  
  1178.     
  1179.     def _done(self):
  1180.         self._line_consumed = 1
  1181.         self.read = self._file.read
  1182.         self.readline = self._file.readline
  1183.         self.readlines = self._file.readlines
  1184.  
  1185.     
  1186.     def read(self, amt = None):
  1187.         if self._line_consumed:
  1188.             return self._file.read(amt)
  1189.         
  1190.         if amt is None or amt > self._line_left:
  1191.             s = self._line[self._line_offset:]
  1192.             self._done()
  1193.             if amt is None:
  1194.                 return s + self._file.read()
  1195.             else:
  1196.                 return s + self._file.read(amt - len(s))
  1197.         else:
  1198.             i = self._line_offset
  1199.             j = i + amt
  1200.             s = self._line[i:j]
  1201.             self._line_offset = j
  1202.             self._line_left -= amt
  1203.             if self._line_left == 0:
  1204.                 self._done()
  1205.             
  1206.             return s
  1207.  
  1208.     
  1209.     def readline(self):
  1210.         if self._line_consumed:
  1211.             return self._file.readline()
  1212.         
  1213.         s = self._line[self._line_offset:]
  1214.         self._done()
  1215.         return s
  1216.  
  1217.     
  1218.     def readlines(self, size = None):
  1219.         if self._line_consumed:
  1220.             return self._file.readlines(size)
  1221.         
  1222.         L = [
  1223.             self._line[self._line_offset:]]
  1224.         self._done()
  1225.         if size is None:
  1226.             return L + self._file.readlines()
  1227.         else:
  1228.             return L + self._file.readlines(size)
  1229.  
  1230.  
  1231.  
  1232. def test():
  1233.     '''Test this module.
  1234.  
  1235.     A hodge podge of tests collected here, because they have too many
  1236.     external dependencies for the regular test suite.
  1237.     '''
  1238.     import sys as sys
  1239.     import getopt as getopt
  1240.     (opts, args) = getopt.getopt(sys.argv[1:], 'd')
  1241.     dl = 0
  1242.     for o, a in opts:
  1243.         if o == '-d':
  1244.             dl = dl + 1
  1245.             continue
  1246.     
  1247.     host = 'www.python.org'
  1248.     selector = '/'
  1249.     if args[0:]:
  1250.         host = args[0]
  1251.     
  1252.     if args[1:]:
  1253.         selector = args[1]
  1254.     
  1255.     h = HTTP()
  1256.     h.set_debuglevel(dl)
  1257.     h.connect(host)
  1258.     h.putrequest('GET', selector)
  1259.     h.endheaders()
  1260.     (status, reason, headers) = h.getreply()
  1261.     print 'status =', status
  1262.     print 'reason =', reason
  1263.     print 'read', len(h.getfile().read())
  1264.     print 
  1265.     if headers:
  1266.         for header in headers.headers:
  1267.             print header.strip()
  1268.         
  1269.     
  1270.     print 
  1271.     
  1272.     class HTTP11(HTTP):
  1273.         _http_vsn = 11
  1274.         _http_vsn_str = 'HTTP/1.1'
  1275.  
  1276.     h = HTTP11('www.python.org')
  1277.     h.putrequest('GET', 'http://www.python.org/~jeremy/')
  1278.     h.endheaders()
  1279.     h.getreply()
  1280.     h.close()
  1281.     if hasattr(socket, 'ssl'):
  1282.         for host, selector in (('sourceforge.net', '/projects/python'),):
  1283.             print 'https://%s%s' % (host, selector)
  1284.             hs = HTTPS()
  1285.             hs.set_debuglevel(dl)
  1286.             hs.connect(host)
  1287.             hs.putrequest('GET', selector)
  1288.             hs.endheaders()
  1289.             (status, reason, headers) = hs.getreply()
  1290.             print 'status =', status
  1291.             print 'reason =', reason
  1292.             print 'read', len(hs.getfile().read())
  1293.             print 
  1294.             if headers:
  1295.                 for header in headers.headers:
  1296.                     print header.strip()
  1297.                 
  1298.             
  1299.             print 
  1300.         
  1301.     
  1302.  
  1303. if __name__ == '__main__':
  1304.     test()
  1305.  
  1306.